package part4;

import java.io.*;

public class DeepProtoType implements Serializable, Cloneable {
    public String name;
    public DeepCloneableTarget deepCloneableTarget;

    public DeepProtoType() {
        super();
    }

    @Override
    public String toString() {
        return "DeepProtoType{" +
                "name='" + name + '\'' +
                ", deepCloneableTarget=" + deepCloneableTarget.hashCode() +
                '}';
    }

    // 方法1，使用clone方法
    @Override
    public DeepProtoType clone() {
        Object deep = null;
        // 对基本数据类型进行克隆
        try {
            deep = super.clone();
            // 对引用数据进行单独的处理
            DeepProtoType deepProtoType = (DeepProtoType) deep;
            deepProtoType.deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();
            // 如果引用很多就很麻烦
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return (DeepProtoType) deep;
    }

    // 方法2，通过对象的序列化来实现（推荐）
    public DeepProtoType deepClone() {
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        DeepProtoType copy = null;

        try {
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this); // 把当前这个对象以对象流的方式序列化
            bis = new ByteArrayInputStream(bos.toByteArray()); // 把序列化的对象重新复制一份。
            ois = new ObjectInputStream(bis);
            try {
                copy = (DeepProtoType)ois.readObject(); // 把对象再读回来
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            try {
                if (bos != null) {
                    bos.close();
                }
                if (oos != null) {
                    oos.close();
                }
                if (bis != null) {
                    bis.close();
                }
                if (ois != null) {
                    ois.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return copy;
    }
}
